#include "RecordHandler.h"
#include <stdarg.h>
#include <iostream>

#ifndef ZERO
	#define ZERO 0
#endif

#ifndef MAX_SIZE
	#define MAX_SIZE 4096
#endif

RecordHandler::RecordHandler()
{
}

RecordHandler::~RecordHandler()
{
}

int RecordHandler::sizeofField(int tipo, int longitud)
{
	int aux = tipo & ~UNSIGNED;	
	switch(aux)
	{
		case CHAR: return sizeof(char) * longitud;
		case INT: return sizeof(int);
		case LONG: return sizeof(long);
		case FLOAT: return sizeof(double);
		case DOUBLE: return sizeof(double);
		default : return ZERO;
	};
}

int RecordHandler::REG_SIZEOF(const campo *esq)
{
	int size  = ZERO;
	
	if(!esq)
		return ZERO;
	for(; esq->nombre; esq++)
	{
		size += sizeofField(esq->tipo, esq->longitud);
	}
	
	return size + sizeof(unsigned int);
}

int RecordHandler::REG_SET(void *buf, const campo * esq, const char *desc, ...)
{
	va_list marker;
	int offset, i=0, tipo, len;
	unsigned int sizeRecord;
	const char *token, *strfield;
	char str[MAX_SIZE];
	char aux[MAX_SIZE];
	
	if( !buf || !esq || !desc)
		return RES_ERROR;
		
	memset(aux, 0, MAX_SIZE);
	memset(str, 0, MAX_SIZE);

	sizeRecord = RecordHandler::REG_SIZEOF(esq);
		
	strcpy(str, desc);
	va_start(marker, desc);
	token = strtok(str, ", ");
	while(token)
	{
		for(offset = 0, i = 0; esq[i].nombre && strcmp(esq[i].nombre, token); offset += sizeofField(esq[i].tipo, esq[i].longitud), i++);
		
		if(esq[i].nombre)
		{
			tipo = esq[i].tipo & ~UNSIGNED;
			
			switch(tipo)
			{
				case INT: *(int*)((char*)buf+offset) = va_arg(marker, int); break;
				case LONG: *(long*)((char*)buf+offset) = va_arg(marker, long); break;
				case FLOAT: *(double*)((char*)buf+offset) = va_arg(marker, double);  break;
				case DOUBLE: *(double*)((char*)buf+offset) = va_arg(marker, double); break;
				case CHAR: 
					strfield = va_arg(marker, char*);
					len = strlen(strfield);
					if(len > esq[i].longitud) len = esq[i].longitud;
					memcpy((char*)buf+offset, strfield, len*sizeof(char));
					memset((char*)buf+offset+len, ZERO, esq[i].longitud - len);
					break;
				default : return RES_ERROR;
			}
		}
		token = strtok(ZERO, ", ");
		
	}
	va_end(marker);

	((unsigned int*)aux)[ZERO] = sizeRecord - sizeof(unsigned int);
	memcpy(aux + sizeof(unsigned int), buf, sizeRecord - sizeof(unsigned int));
	memcpy(buf, aux, sizeRecord);

	return RES_OK;
}

int RecordHandler::REG_GET(const void *buf, const campo *esq, const char* desc, ...)
{
	va_list marker;
	int offset, i;
	const char *token;
	char str[MAX_SIZE];
	
	if( !buf || !esq || !desc)
		return RES_ERROR;
		
	strcpy(str, desc);
	va_start(marker, desc);
	token = strtok(str, ", ");
	while(token)
	{
		for(offset = ZERO, i = ZERO; esq[i].nombre && strcmp(esq[i].nombre, token); offset += sizeofField(esq[i].tipo, esq[i].longitud), i++);
		if(esq[i].nombre)
			memcpy(va_arg(marker, void *), (const char*)buf+offset+sizeof(unsigned int), sizeofField(esq[i].tipo, esq[i].longitud));
		token = strtok(0, ", ");
	}
	va_end(marker);
	return RES_OK;
	
}
